package sshconfig

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
	"strings"

	"go.uber.org/zap"
	"gitee.com/liumou_site/ssh-go-automatic-upgrade/internal/service"
)

// SSHConfigManager SSH配置管理器
// 负责配置文件的修改和SSH服务管理
type SSHConfigManager struct {
	configPath string
	serviceMgr *service.ServiceManager
}

// NewSSHConfigManager 创建SSH配置管理器
func NewSSHConfigManager() *SSHConfigManager {
	return &SSHConfigManager{
		configPath: "/etc/ssh/sshd_config",
		serviceMgr: service.NewServiceManager("sshd"),
	}
}

// ConfigFileExists 检查配置文件是否存在
func (m *SSHConfigManager) ConfigFileExists() bool {
	_, err := os.Stat(m.configPath)
	return !os.IsNotExist(err)
}

// SetRootLogin 设置root登录权限
func (m *SSHConfigManager) SetRootLogin(enable bool, force bool) (bool, string) {
	zap.L().Info("设置root登录权限")

	if !m.ConfigFileExists() && !force {
		return false, "配置文件不存在，使用force参数强制创建"
	}

	// 读取现有内容或创建新文件
	var lines []string
	if m.ConfigFileExists() {
		content, err := os.ReadFile(m.configPath)
		if err != nil {
			return false, fmt.Sprintf("读取配置文件失败: %v", err)
		}
		lines = strings.Split(string(content), "\n")
	} else {
		lines = []string{}
	}

	// 构建新的设置行
	settingValue := "yes"
	if !enable {
		settingValue = "no"
	}
	newSettingLine := fmt.Sprintf("PermitRootLogin %s", settingValue)

	// 查找并替换现有的PermitRootLogin设置
	pattern := regexp.MustCompile(`^\s*(#?)\s*PermitRootLogin\s+\S+`)
	found := false
	newLines := []string{}

	for _, line := range lines {
		if pattern.MatchString(line) {
			if !found {
				// 替换第一个匹配的设置
				newLines = append(newLines, newSettingLine)
				found = true
			}
			// 跳过其他匹配的设置
		} else {
			newLines = append(newLines, line)
		}
	}

	// 如果没有找到现有设置，在文件末尾添加
	if !found {
		// 确保文件以换行符结束
		if len(newLines) > 0 && !strings.HasSuffix(newLines[len(newLines)-1], "\n") {
			newLines[len(newLines)-1] = newLines[len(newLines)-1] + "\n"
		}
		newLines = append(newLines, newSettingLine)
	}

	// 写入新内容
	file, err := os.Create(m.configPath)
	if err != nil {
		return false, fmt.Sprintf("创建配置文件失败: %v", err)
	}
	defer file.Close()

	writer := bufio.NewWriter(file)
	for _, line := range newLines {
		_, err := writer.WriteString(line + "\n")
		if err != nil {
			return false, fmt.Sprintf("写入配置文件失败: %v", err)
		}
	}
	writer.Flush()

	// 设置正确的文件权限
	os.Chmod(m.configPath, 0644)

	action := "启用"
	if !enable {
		action = "禁用"
	}
	zap.L().Info("root登录已设置", zap.String("action", action))
	return true, fmt.Sprintf("root登录已%s", action)
}

// SetKeyOnlyLogin 设置仅密钥登录（禁用密码认证）
func (m *SSHConfigManager) SetKeyOnlyLogin(enable bool, force bool) (bool, string) {
	zap.L().Info("设置仅密钥登录")

	if !m.ConfigFileExists() && !force {
		return false, "配置文件不存在，使用force参数强制创建"
	}

	// 读取现有内容或创建新文件
	var lines []string
	if m.ConfigFileExists() {
		content, err := os.ReadFile(m.configPath)
		if err != nil {
			return false, fmt.Sprintf("读取配置文件失败: %v", err)
		}
		lines = strings.Split(string(content), "\n")
	} else {
		lines = []string{}
	}

	// 构建新的设置行
	settingValue := "no"
	if !enable {
		settingValue = "yes"
	}
	newSettingLine := fmt.Sprintf("PasswordAuthentication %s", settingValue)

	// 查找并替换现有的PasswordAuthentication设置
	pattern := regexp.MustCompile(`^\s*(#?)\s*PasswordAuthentication\s+\S+`)
	found := false
	newLines := []string{}

	for _, line := range lines {
		if pattern.MatchString(line) {
			if !found {
				// 替换第一个匹配的设置
				newLines = append(newLines, newSettingLine)
				found = true
			}
			// 跳过其他匹配的设置
		} else {
			newLines = append(newLines, line)
		}
	}

	// 如果没有找到现有设置，在文件末尾添加
	if !found {
		// 确保文件以换行符结束
		if len(newLines) > 0 && !strings.HasSuffix(newLines[len(newLines)-1], "\n") {
			newLines[len(newLines)-1] = newLines[len(newLines)-1] + "\n"
		}
		newLines = append(newLines, newSettingLine)
	}

	// 写入新内容
	file, err := os.Create(m.configPath)
	if err != nil {
		return false, fmt.Sprintf("创建配置文件失败: %v", err)
	}
	defer file.Close()

	writer := bufio.NewWriter(file)
	for _, line := range newLines {
		_, err := writer.WriteString(line + "\n")
		if err != nil {
			return false, fmt.Sprintf("写入配置文件失败: %v", err)
		}
	}
	writer.Flush()

	// 设置正确的文件权限
	os.Chmod(m.configPath, 0644)

	action := "启用"
	if !enable {
		action = "禁用"
	}
	zap.L().Info("仅密钥登录已设置", zap.String("action", action))
	return true, fmt.Sprintf("仅密钥登录已%s", action)
}

// RestartSSHService 重启SSH服务使配置生效
func (m *SSHConfigManager) RestartSSHService() error {
	zap.L().Info("重启SSH服务")
	return m.serviceMgr.RestartService()
}

// GetSSHServiceStatus 获取SSH服务状态
func (m *SSHConfigManager) GetSSHServiceStatus() (string, error) {
	zap.L().Info("获取SSH服务状态")
	return m.serviceMgr.GetServiceStatus()
}

// StartSSHService 启动SSH服务
func (m *SSHConfigManager) StartSSHService() error {
	zap.L().Info("启动SSH服务")
	return m.serviceMgr.StartService()
}

// StopSSHService 停止SSH服务
func (m *SSHConfigManager) StopSSHService() error {
	zap.L().Info("停止SSH服务")
	return m.serviceMgr.StopService()
}